#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <fcntl.h>
#include "model.h"

/* marche pas ?*/

void rec_rbmp(data ndata,int fp,size_t h,size_t w, size_t bpp){
	size_t y,i,v;
	char *tr = malloc (4);
	ndata->ar = malloc (w*h*sizeof(struct pixdat));
		for(i = h; i>=0;--i){
			for(y = 0; y<w;++y){
				fread(&(ndata->ar[i*w+y].b),1,1,fp);
           		fread(&(ndata->ar[i*w+y].g),1,1,fp);
				fread(&(ndata->ar[i*w+y].r),1,1,fp);
				if(bpp == 32)
				{
					fread(&(ndata->ar[i*w+y].a),1,1,fp);
				}
				else
					ndata->ar[i*w+y].a = 0;
			}
			read(fp,tr,((4 - (y*3%4))%4));
		}
	free(tr);
}

void rec_pbmp(data ndata,int fp,size_t h,size_t w, size_t bpp,struct pixdat *ar,int cmp){
   size_t y,i,v;
	int	n;
	char	byt;
	unsigned char mask_table[] = { 0x01, 0x02, 0x04, 0x08, 0x10, 0x20, 0x40, 0x80 };
	ndata->ar = malloc (w*h*sizeof(struct pixdat));
	if(cmp == 1 || cmp == 2 ){
        for(i = h; i>=0;--i){
            for(y = 0; y<w;y){
					fread(&byt,1,1,fp);
						n = (int)byt;
						fread(&byt,1,1,fp);
					if(bpp == 4 ){
						if(n != 0){
							for(v = 0;v<=n;v){
							ndata->ar[i*w+y] = ar[(int)byt/16];
							y++;
							v++;
								if(v<=n){
								ndata->ar[i*w+y] = ar[(int)byt%16];
								y++;
								v++;
								}
							}
						}
						else{
							if((int)byt == 0){
							break;
							}
							if((int)byt == 1){
							return(NULL);
							}
							if((int)byt == 2){
							fread(&byt,1,1,fp);
							y=+(int)byt;
							fread(&byt,1,1,fp);
							i=-(int)byt;
							}
						}
					}
					if(bpp == 8){
						 if(n != 0){
					        for(v = 0;v<=n;v){
			                  ndata->ar[i*w+y] = ar[(int)byt];
	   	                  y++;
			                  v++;
						         }
						     }
						 else{
						    if((int)byt == 0){
							     break;
							 }
							 if((int)byt == 1){
							     return(NULL);
							 }
							 if((int)byt == 2){
							     fread(&byt,1,1,fp);
							     y=+(int)byt;
							     fread(&byt,1,1,fp);
							     i=-(int)byt;
				      	 }
				  		 }
				 	}
			   }
			}
      }
	else{
		for(i = h; i>=0;--i){
	  	 for(y = 0; y<w;y){
	 		  fread(&byt,1,1,fp);
			  	if(bpp == 1){
					for(v = 7;v>=0;v--){
					ndata->ar[i*w+y] = ar[((byt & mask_table[v]) != 0x00)];
					y++;
					}
				}
			  	if(bpp == 4){
				ndata->ar[i*w+y] = ar[(int)byt/16];
				y++;
				ndata->ar[i*w+y] = ar[(int)byt%16];
				y++;
			  	}
				if(bpp == 8){
				ndata->ar[i*w+y] = ar[(int)byt];
				y++;
				}
			}
		}
        }
}

struct pixdat  *make_pal(int fp,int bpp){
    size_t i = 1<<bpp;
    size_t j;
    struct pixdat  *pal = malloc(i*sizeof(struct pixdat));

    for(j = 0;j<i;j++){
        fseek(fp,1,SEEK_CUR);
        fread(&(pal[j].r),1,1,fp);
        fread(&(pal[j].g),1,1,fp);
        fread(&(pal[j].b),1,1,fp);
        pal[j].a = 0;
    }
    return pal;
}

// Need to add ar making
data bmp2data(char *path){
	data ndata;
	char *tr = malloc (4);
	size_t bpp;
	size_t start;
	size_t cmp;
	char *sign;
	size_t s;
	size_t dib;
	struct pixdat *pal;
	ndata = malloc(sizeof(struct s_data));
	int fp = open(path,O_RDONLY);
	if(fp<=0)
		perror("Can't open file");
	// Read "BM"on the header
	fread(tr,1, 2,fp);
	// Check if the file is BM
	if (strcmp(tr,"BM")){
	// Read file size
		fread(&s,4,1,fp);
	// Skip 4 bytes
		fseek(fp,4,SEEK_CUR);
	// Store start of data
		fread(&start, 4,1,fp);
	// Read header size
		fread(&dib, 4,1,fp);
	// BITMAPINFOHEADER (windows version 3.0+
		if(dib == 40)
		{
			// Store size of the image
			fread(&(ndata->w),4,1,fp);
			fread(&(ndata->h),4,1,fp);
			// Skip 2 bit, not useful
			fseek(fp,2,SEEK_CUR);
			// Get nu;ber of byte ber pixel
			fread(&bpp,2,1,fp);
			// Read the compression method
			fread(&cmp,4,1,fp);
			// Get resolution of the image in pix per meter
			fread(&(ndata->rw),4,1,fp);
			fread(&(ndata->rh),4,1,fp);
			// Get the size of the palette;
			fread(&pal,4,1,fp);
			fseek(fp,4,SEEK_CUR);
			if(bpp>=24 & cmp == 0){
				fseek(fp, start,SEEK_SET);
				rec_rbmp(ndata,fp,ndata->h,ndata->w,bpp);
			}
			else if(bpp <= 8){
                pal = make_pal(fp,bpp);
				fseek(fp, start,SEEK_SET);
				rec_pbmp(ndata,fp,ndata->h,ndata->w,bpp,pal,cmp);
			}
		}
	}
	else if(strcmp(tr,0)){
              // some windows stuff...
	}
	close(fp);
	free(tr);
	return ndata;
}

void clr(char *buff,size_t s){
    for(s;s>=0;s--){
    buff[s] = 0;
    }
}

void data2bmp(data bdata,char *name){
	int s = 0;
	int raw;
	int i,j,m;
	int fi = open(name, O_CREAT | O_TRUNC | O_EXCL /*| O_NOCTTY */| O_WRONLY,0666);
	char *buff = malloc(4);
	buff = "BM";
	fwrite(buff,1,2,fi);
	fwrite(buff,2,2,fi);
	buff = "BTBT";
	fwrite(buff,1,4,fi);

    clr(buff,3);
    buff[0] = 54; //gotta test this shit
	fwrite(buff,4,1,fi);
	buff[0] = 40;
	fwrite(buff,4,1,fi);

	fwrite(&(bdata->w),2,1,fi);
    fwrite(&(bdata->h),2,1,fi);

	buff[0] = 1;
	fwrite(buff,2,1,fi);
	buff[0] = 24;
	fwrite(buff,2,1,fi);
	buff[0] = 0;
	fwrite(buff,4,1,fi);

	raw = ftell(fi);

	fwrite(buff,4,1,fi);
	fwrite(&(bdata->rw),4,1,fi);
    fwrite(&(bdata->rh),4,1,fi);

    fwrite(buff,4,1,fi);
    fwrite(buff,4,1,fi);

	m = ((4-(bdata->w*3)%4)%4);
	for(i = (bdata->h)-1; i>=0;--i){
		for(j = 0; j<bdata->w;++j){
			fwrite(&(bdata->ar[i*bdata->w + j].b),1,1,fi);
            fwrite(&(bdata->ar[i*bdata->w + j].g),1,1,fi);
            fwrite(&(bdata->ar[i*bdata->w + j].r),1,1,fi);
			s+=3;
		}
		fwrite(buff,m,1,fi);
		s +=m;
	}
	fseek(fi, raw,SEEK_SET);
	buff[0] = s;
	fwrite(buff,1,4,fi);
	fseek(fi,2,SEEK_SET);
	buff[0] = s+54;
	fwrite(buff,1,4,fi);
	free(buff);
	close(fi);
}

void main (int arg,char *argv[]){
    int i;
    data n = malloc(sizeof(struct s_data));
    struct pixdat *pix = malloc(400*sizeof(struct pixdat));
    for(i = 0;i<400;i++){
        pix[i].r = 255;
        pix[i].g = 255;
        pix[i].b = 255;
        pix[i].a = 0;
    }
    n->w = 30;
    n->h = 10;
    n->rh = 10;
    n->rw = 40;
    data2bmp(n,"test.bmp");
}
